#include "Demo.h"
#include <windowsx.h>
#include "resource.h"
#pragma comment(lib, "Msimg32.lib")
//////////////////////////////////////////////////////////////////////////
// CDemoApp
//////////////////////////////////////////////////////////////////////////
CDemoApp::CDemoApp()
{

}

CDemoApp::~CDemoApp()
{

}

bool CDemoApp::InitInstance()
{
	m_pMainWnd = new CDemoWnd();
	m_pMainWnd->ShowWindow(SW_SHOW);
																   
	return true;
}

//////////////////////////////////////////////////////////////////////////
// CDemoWnd
//////////////////////////////////////////////////////////////////////////
#define MSGHANDLE(nMsg, MsgProc)  {(nMsg), (&CDemoWnd::MsgProc)}

const CDemoWnd::TMSGMAP CDemoWnd::MsgMapTable[] = {
	MSGHANDLE(WM_CREATE,		OnCreate),
	MSGHANDLE(WM_DESTROY,		OnDestroy), 
	MSGHANDLE(WM_PAINT,			OnPaint),
};

CDemoWnd::CDemoWnd(const TCHAR* szAppName)
{
	Create(szAppName, WS_OVERLAPPEDWINDOW, 0, 0, 1280, 720, NULL);
}

CDemoWnd::~CDemoWnd()
{
}

LRESULT	 CDemoWnd::WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	for (int ii = 0; ii < sizeof(MsgMapTable) / sizeof(*MsgMapTable); ii++)
	{
		if (nMsg == MsgMapTable[ii].m_nMsg)
		{
			(this->*MsgMapTable[ii].m_MsgProc)(hWnd, nMsg, wParam, lParam);
			break;
		}
	}

	return __super::FinalWndProc(hWnd, nMsg, wParam, lParam);
}

LRESULT CDemoWnd::OnCreate(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	CenterWindow();
	m_hBitmap = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1));
	m_hBitmap2 = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP2));

	return 0;
}

LRESULT CDemoWnd::OnDestroy(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	PostQuitMessage(0);

	return 0;
}

LRESULT CDemoWnd::OnPaint(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
	HDC hDC = BeginPaint(hWnd, &ps);
	
	const UINT nGridCount = 6;
	RECT rtGrids[nGridCount];
	_PartitionGrid(hDC, rtGrids, nGridCount);

	int nIndex = 0;
	_BitBltBmp(hDC, rtGrids[nIndex++]);
 
	_StretchBltBmp(hDC, rtGrids[nIndex++]);

	_PatBltBmp(hDC, rtGrids[nIndex++]);

	_BlendBmp(hDC, rtGrids[nIndex++]);

	_TransparentBltBmp(hDC, rtGrids[nIndex++]);
		
	_MaskBltBmp(hDC, rtGrids[nIndex++]);

	EndPaint(hWnd, &ps);

	return 1;
}

//////////////////////////////////////////////////////////////////////////
// following Demo code 
//////////////////////////////////////////////////////////////////////////
void CDemoWnd::_PartitionGrid(HDC hDC, RECT* prtGrids, int nGridCount)
{
	assert(0 < nGridCount);

	//--: Grids rect area
	RECT rtClient;
	GetClientRect(m_hWnd, &rtClient);
	InflateRect(&rtClient, -5, -5);

	//==: calculate every grid rect and paint color
	HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, GetStockObject(DC_BRUSH));
	SetDCBrushColor(hDC, RGB(220, 220, 220));
	Rectangle(hDC, rtClient.left, rtClient.top, rtClient.right, rtClient.bottom);

	RECT rtDemo;
	CopyRect(&rtDemo, &rtClient);
	int nHeight = (rtDemo.bottom - rtDemo.top) / nGridCount;

	for (int ii = 0; ii < nGridCount; ii++)
	{
		int y = rtDemo.top + nHeight * ii;
		SetRect(&prtGrids[ii], rtDemo.left, y, rtDemo.right, y + nHeight);

		Rectangle(hDC, prtGrids[ii].left, prtGrids[ii].top, prtGrids[ii].right, prtGrids[ii].bottom);
	}

	SelectObject(hDC, hOldBrush);

	return;
}

void CDemoWnd::_BitBltBmp(HDC hDC, RECT& rtGrids)
{
	const UINT nWidth = rtGrids.right - rtGrids.left;
	const UINT nHeight = rtGrids.bottom - rtGrids.top;	
	
	HDC hMemDC = CreateCompatibleDC(hDC);
	HGDIOBJ hGDIObj = SelectObject(hMemDC, m_hBitmap);
	
	BitBlt(hDC, rtGrids.left, rtGrids.top, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);

	SelectObject(hMemDC, hGDIObj);
	DeleteObject(hMemDC);

	return;
}

void CDemoWnd::_StretchBltBmp(HDC hDC, RECT& rtGrids)
{
	const UINT nWidth = rtGrids.right - rtGrids.left;
	const UINT nHeight = rtGrids.bottom - rtGrids.top;	

	HDC hMemDC = CreateCompatibleDC(hDC);
	HGDIOBJ hGDIObj = SelectObject(hMemDC, m_hBitmap);

	BITMAP bmp;
	GetObject(m_hBitmap, sizeof(BITMAP), &bmp);
	StretchBlt(hDC, rtGrids.left, rtGrids.top, nWidth, nHeight, hMemDC, 0, 0, bmp.bmWidth, nHeight, SRCCOPY);

	SelectObject(hMemDC, hGDIObj);
	DeleteObject(hMemDC);

	return;
}

void CDemoWnd::_PatBltBmp(HDC hDC, RECT& rtGrids)
{
	HBRUSH hBrush	= CreatePatternBrush(m_hBitmap);
	HGDIOBJ hGDIObj = SelectObject(hDC, hBrush);

	const UINT nWidth = rtGrids.right - rtGrids.left;
	const UINT nHeight = rtGrids.bottom - rtGrids.top;	

	PatBlt(hDC, rtGrids.left, rtGrids.top, nWidth, nHeight, PATCOPY);
	SelectObject(hDC, hGDIObj);

	return;
}

void CDemoWnd::_BlendBmp(HDC hDC, RECT& rtGrids)
{
	const UINT nWidth = rtGrids.right - rtGrids.left;
	const UINT nHeight = rtGrids.bottom - rtGrids.top;	

	HDC hMemDC = CreateCompatibleDC(hDC);
	HGDIOBJ hGDIObj = SelectObject(hMemDC, m_hBitmap);
	
	BITMAP bmp;
	GetObject(m_hBitmap, sizeof(BITMAP), &bmp);
	BLENDFUNCTION bf;
	bf.BlendOp				= AC_SRC_OVER;
	bf.BlendFlags			= 0;
	bf.SourceConstantAlpha	= 64;
	bf.AlphaFormat			= AC_SRC_ALPHA;
	AlphaBlend(hDC, rtGrids.left, rtGrids.top, nWidth, nHeight, hMemDC, 0, 0, bmp.bmWidth, nHeight, bf);

	SelectObject(hMemDC, hGDIObj);
	DeleteObject(hMemDC);

	return;
}

void CDemoWnd::_TransparentBltBmp(HDC hDC, RECT& rtGrids)
{
	const UINT nWidth = rtGrids.right - rtGrids.left;
	const UINT nHeight = rtGrids.bottom - rtGrids.top;

	BITMAP bmp;
	GetObject(m_hBitmap, sizeof(BITMAP), &bmp);

	HDC hMemDC = CreateCompatibleDC(hDC);
	HGDIOBJ hGDIObj		= SelectObject(hMemDC, m_hBitmap2);
	TransparentBlt(hDC, rtGrids.left, rtGrids.top, nWidth, nHeight, hMemDC, 0, 0, bmp.bmWidth, nHeight, RGB(255, 255, 255));

	SelectObject(hMemDC, hGDIObj);
	DeleteObject(hMemDC);

	return;
}

void CDemoWnd::_MaskBltBmp(HDC hDC, RECT& rtGrids)
{
	const UINT nWidth = rtGrids.right - rtGrids.left;
	const UINT nHeight = rtGrids.bottom - rtGrids.top;

	BITMAP bmp;
	GetObject(m_hBitmap, sizeof(BITMAP), &bmp);

	HDC hMemDC = CreateCompatibleDC(hDC);
	HGDIOBJ hGDIObj	= SelectObject(hMemDC, m_hBitmap2);

	HDC hBufDC = CreateCompatibleDC(hDC);
	HBITMAP hBmp1 = CreateCompatibleBitmap(hDC, bmp.bmWidth, bmp.bmHeight);
	HGDIOBJ hGDIObj2 = SelectObject(hBufDC, hBmp1);

	HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 255));
	FillRect(hBufDC, &rtGrids, hBrush);
		
	BitBlt(hDC, rtGrids.left, rtGrids.top, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);

	HBITMAP hMskBmp = CreateBitmap(nWidth, nHeight, 1, 1, NULL);

	MaskBlt(hDC, rtGrids.left, rtGrids.top, nWidth, nHeight, hBufDC, 0, 0, hMskBmp, 0, 0, SRCCOPY|0xCCAA0020 );

	SelectObject(hMemDC, hGDIObj);
	DeleteObject(hMemDC);

	return;
}